package com.example.androlem2;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

import lem2.logic.SISet;
import lem2.logic.SISetArray;
import lem2.logic.SISetFactory;
import lem2.logic.SIUtils;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.method.KeyListener;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabWidget;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;



public class MainActivity extends Activity {
	TabWidget tw ;
	TabHost th;
	
	int currentCol =0;
	
	int rowCount =2;
	int colCount =2;
	
	String [][] table ;
	ArrayList<ArrayList<String>> columns;
	ArrayList<ArrayList<String>> attrValues;
	String [] attrNames;
	
	static final String FIRST_TAB = "1. Initialize";
	static final String CREATE_TABLE_TAB = "2. Table Create";
	static final String RESULT_TAB = "3. Result";
	static final String TEST_TAB = "4. TEST";
	
	LayoutInflater inflater;
	EditText rowCountET, colCountET;
	
	EditText attrValueET, attrNameET;
	Button nextBT, prevBT, addValueBT;
	ViewFlipper viewFlipper;
	ListView [] listViews;
	TextView columnNumberTV;
	
	TextView resultTV;
	
	Drawable editingDrawable, normalDrawable;
	KeyListener keyListener;
	
	TableLayout tableLayout;
	
	
	@Override
	protected void onStop() {
		try {
			SaveState ss = new SaveState(columns,attrValues,attrNames,rowCount, colCount);
			ObjectOutputStream oos = new ObjectOutputStream(openFileOutput("androlemcahe", Context.MODE_PRIVATE));
			Log.w("tmpfile",  "STATE SAVED");
			oos.writeObject(ss);
			oos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		super.onStop();
	}
	
	@Override
	protected void onStart() {
		SaveState ss = null;
		try {
			ObjectInputStream ois = new ObjectInputStream(openFileInput("androlemcahe"));
			Log.w("tmpfile",  "STATE READED");
			ss = (SaveState) ois.readObject();
			ois.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		if(ss != null){
			columns = ss.columns;
			attrNames = ss.attrNames;
			attrValues = ss.attrValues;
			rowCountET.setText(String.valueOf(ss.rowCount));
			colCountET.setText(String.valueOf(ss.colCount));
		}
		createDataContainers(ss);
		setFillViews();
		super.onStart();
	}
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
		setContentView(R.layout.activity_main);
		
		th = (TabHost) findViewById(android.R.id.tabhost);
		tw = th.getTabWidget();
		th.setup();
		
		th.addTab(th.newTabSpec(FIRST_TAB).setIndicator(FIRST_TAB).setContent(R.id.firstTab));
		th.addTab(th.newTabSpec(CREATE_TABLE_TAB).setIndicator(CREATE_TABLE_TAB).setContent(R.id.tabTableCreate));
		th.addTab(th.newTabSpec(RESULT_TAB).setIndicator(RESULT_TAB).setContent(R.id.resultTab));
		th.addTab(th.newTabSpec(TEST_TAB).setIndicator(TEST_TAB).setContent(R.id.testTab));
		th.setCurrentTabByTag(FIRST_TAB);
		
		th.setOnTabChangedListener(otchlistener);
		
		rowCountET = (EditText) findViewById(R.id.rowCount);
		rowCountET.setText(String.valueOf(rowCount));
		colCountET = (EditText) findViewById(R.id.colCount);
		colCountET.setText(String.valueOf(colCount));
		
		resultTV = (TextView) findViewById(R.id.resultTV);
		resultTV.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/cour.ttf"));
		Button calc = (Button) findViewById(R.id.calculateBT);
		calc.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				calculate();
			}
		});
		
		Button setRowSize = (Button) findViewById(R.id.setTableSizeBT);
		setRowSize.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				createDataContainers(null);
				setFillViews();
			}
		});
		
		Button loadTable = (Button) findViewById(R.id.loadTable);
		loadTable.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				File dir = Environment.getExternalStorageDirectory();
				dir = new File(dir.getAbsolutePath()+"/androlem2/tables");
				final File [] list = dir.listFiles(tabFileFilter);
				
				if(list == null){
					new AlertDialog.Builder(MainActivity.this)
					.setTitle("Directory not exists.")
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setMessage("["+dir.getAbsolutePath()+"]" + " is not created")
					.show();
					return;
				}
				else if(list.length == 0){
					new AlertDialog.Builder(MainActivity.this)
					.setTitle("Directory is empty")
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setMessage("There's not files (*.tab) in directory [" +dir.getAbsolutePath()+ "]" )
					.show();
					return;
				}
				
				String [] names = new String [list.length];
				for(int i=0;i<list.length;i++){
					names[i] = list[i].getName();
				}
				
				new AlertDialog.Builder(MainActivity.this)
				.setTitle("Select file")
				.setIcon(android.R.drawable.ic_dialog_info)
				.setItems(names, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						try {
							setStateFromTable(SIUtils.tabFileToTable(list[which]));
							Toast.makeText(MainActivity.this, "Load sucessfull!", Toast.LENGTH_LONG).show();
						} catch (IOException e) {
							Toast.makeText(MainActivity.this, "Load failed!", Toast.LENGTH_LONG).show();
							e.printStackTrace();
						}
					}
				})
				.show();
				
				
				
				Log.i("", "");
			}
		});
		
		ViewGroup tabableCreateGroup = (ViewGroup) inflater.inflate(R.layout.tablecreate, null);
		
		nextBT = (Button) tabableCreateGroup.findViewById(R.id.next);
		nextBT.setOnClickListener(clickListener);
		prevBT = (Button) tabableCreateGroup.findViewById(R.id.prev);
		prevBT.setOnClickListener(clickListener);
		addValueBT = (Button) tabableCreateGroup.findViewById(R.id.addValBT);
		addValueBT.setOnClickListener(clickListener);
		
		attrValueET = (EditText) tabableCreateGroup.findViewById(R.id.attrvalET);
		attrNameET = (EditText) tabableCreateGroup.findViewById(R.id.attrnameET);
		
		editingDrawable = getResources().getDrawable(android.R.drawable.edit_text);
		normalDrawable = getResources().getDrawable(android.R.drawable.edit_text);
		normalDrawable.setColorFilter(Color.LTGRAY, Mode.SRC_ATOP);
		
		setAttribNameEditMode(false);
		attrNameET.setOnLongClickListener(longClickListener);
		
		
		attrNameET.setOnFocusChangeListener(new OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if(!hasFocus){
					setAttribNameEditMode(false);
				}
			}
		});
		
		columnNumberTV = (TextView) tabableCreateGroup.findViewById(R.id.colNumberTV);
		
		LinearLayout tableCreateView = (LinearLayout) findViewById(R.id.tabTableCreate);
		tableCreateView.addView(tabableCreateGroup);
		
		viewFlipper = (ViewFlipper) tabableCreateGroup.findViewById(R.id.viewSwitcher1);
		
		
		ViewGroup testGroup = (ViewGroup) inflater.inflate(R.layout.test_lay, null);
		tableLayout = (TableLayout) testGroup.findViewById(R.id.table);
		
		ViewGroup testTab = (ViewGroup) findViewById(R.id.testTab);
		testTab.addView(testGroup);
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void createDataContainers(SaveState ss) throws NumberFormatException{
		try {
			
			if(ss != null){
				rowCount = ss.rowCount;
				rowCountET.setText(String.valueOf(ss.rowCount));
				colCount = ss.colCount;
				colCountET.setText(String.valueOf(ss.colCount));
				if(!isTableSizeCorrect()){return;}
				if(ss.columns == null){
					columns = new ArrayList<ArrayList<String>>(colCount);
					for(int i=0;i<colCount;i++){
						ArrayList<String> tmp = new ArrayList<String>(rowCount);
						for(int k=0;k<rowCount;k++){
							tmp.add("---");
						}
						columns.add(tmp);
					}
				}
				else{
					columns = ss.columns;
				}
				if(ss.attrValues == null){
					attrValues = new ArrayList<ArrayList<String>>(colCount);
					for(int i=0;i<colCount;i++){
						attrValues.add(new ArrayList<String>());
					}
				}
				else{
					attrValues = ss.attrValues;
				}
				if(attrNames == null){
					attrNames = new String[colCount];
					for(int i=0;i<colCount;i++){
						attrNames[i] = "";
					}
				}
				else{
					attrNames = ss.attrNames;
				}
				return;
			}
			
			
			rowCount = Integer.valueOf(rowCountET.getText().toString());
			colCount = Integer.valueOf(colCountET.getText().toString());
			if(!isTableSizeCorrect()){return;}
			
			columns = new ArrayList<ArrayList<String>>(colCount);
			attrValues = new ArrayList<ArrayList<String>>(colCount);
			attrNames = new String[colCount];
			
			for(int i=0;i<colCount;i++){
				attrNames[i] = "";
				attrValues.add(new ArrayList<String>());
				ArrayList<String> tmp = new ArrayList<String>(rowCount);
				for(int k=0;k<rowCount;k++){
					tmp.add("---");
				}
				columns.add(tmp);
			}
			
		} catch (NumberFormatException e) {
			rowCount =0;
			colCount =0;
			throw e;
		}
	}
	
	public void setFillViews(){
		viewFlipper.removeAllViews();
		for(int i=0;i<colCount;i++){
			ViewGroup ll = (ViewGroup)inflater.inflate(R.layout.cell_list, null);
			
			ListView tmpLv = (ListView) (ll).findViewById(R.id.listView1);
			ArrayAdapter<String> tmpArad = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, columns.get(i));
			tmpLv.setAdapter(tmpArad);
			tmpLv.setOnItemClickListener(oicl);
			viewFlipper.addView(ll);
		}
		
		viewFlipper.setDisplayedChild(0);
	}
	
	
	
	
	public void createDividedTable(SISetFactory factory, HashMap<String, SISetArray> divided){
		
		int colorRatio = 150 / factory.klasses.length;
		
		
		for(String klass: factory.klasses){
			
			SISetArray localKlassSet = divided.get(klass);
			
			
			TableRow headers = new TableRow(this);
			headers.addView(new TextView(this));
			
			for(String k: factory.klasses){
				TextView tv = new TextView(this);
				tv.setText(k);
				headers.addView(tv);
			}
			
			headers.setBackgroundColor(Color.argb(190, 150, 0, 0));
			
			TableRow.LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			
			lp.gravity = Gravity.BOTTOM;
			
			tableLayout.addView(headers);
			int i=0;
			for(SISet siSet : localKlassSet){
				TableRow tr = new TableRow(this);
				tr.setGravity(Gravity.FILL_VERTICAL);
				String sisetNames = siSet.getFormatedNames();
				TextView sisetNamesTV = new TextView(this);
				sisetNamesTV.setText(sisetNames);
				tr.addView(sisetNamesTV);
				
				
				HashMap<String, String> sisetValues =  siSet.getFormatedValues();
				int cellColor = 50;
				i++;
				for(String klass2 : factory.klasses){
					TextView klassValuesTV = new TextView(this);
					klassValuesTV.setText(sisetValues.get(klass2));
					klassValuesTV.setLayoutParams( lp);
					klassValuesTV.setBackgroundColor(Color.argb((i%2 ==0)?150:230, 0, cellColor += colorRatio, 0));
					tr.addView(klassValuesTV);
				}
				
				tableLayout.addView(tr);
				
			}
			
			
			
		}
	}
	
	public void calculate(){
		table = new String [rowCount+1][colCount];
		
		for(int i=0;i<attrNames.length;i++){
			table[0][i] = attrNames[i];
		}
		for(int i=0;i<columns.size();i++){
			for(int k=0;k<columns.get(0).size();k++){
				table[k+1][i] = columns.get(i).get(k);
			}
		}
		
		SISetFactory factory = new SISetFactory(table);
		
		SISetArray list = factory.createAll();
		
		HashMap<String, SISetArray> divided = factory.divByKlass(list);
		
		createDividedTable(factory, divided);
		
		resultTV.setText("");
		
		for(String s: factory.klasses){
			resultTV.append(divided.get(s).print());
			resultTV.append(divided.get(s).print());
		}
		resultTV.append("------------------RULES-----------------------\n");
		HashMap<String, SISetArray> rule = factory.findRules(divided, null);
		createDividedTable(factory, rule);
		for(String s: factory.klasses){
			resultTV.append(rule.get(s).print());
			resultTV.append("--------------------------------------------\n");
		}
		
	}
	
	public void setAttribNameEditMode(boolean editable){
		if(editable){
			attrNameET.setFocusable(editable);
			attrNameET.setFocusableInTouchMode(editable);
			attrNameET.setBackgroundDrawable(editingDrawable);
		}
		else{
			attrNameET.setFocusable(editable);
			attrNameET.setFocusableInTouchMode(editable);
			attrNameET.setBackgroundDrawable(normalDrawable);
			if(attrNames != null){
				attrNames[viewFlipper.indexOfChild(viewFlipper.getCurrentView())] = attrNameET.getText().toString();
			}
			
		}
	}
	
	public boolean isTableSizeCorrect(){
		return (rowCount < 2 || colCount < 2)? false : true;
	}

	public void setStateFromTable(String [][] table){
		rowCount = table.length-1;
		colCount = table[0].length;
		rowCountET.setText(String.valueOf(rowCount));
		colCountET.setText(String.valueOf(colCount));
		
		this.table= table; 
		
		attrNames = new String[colCount];
		for(int i=0;i<table[0].length;i++){
			attrNames[i] = table[0][i];
		}
		
		columns = new ArrayList<ArrayList<String>>(colCount);
		attrValues = new ArrayList<ArrayList<String>>(colCount);
		for(int i=0;i<colCount;i++){
			attrValues.add(new ArrayList<String>());
			columns.add(new ArrayList<String>(rowCount));
			for(int k=0;k<rowCount;k++){
				String tmp = table[k+1][i];
				columns.get(i).add(tmp);
				if(!SISetFactory.isAttrInArray(attrValues.get(i), tmp)){
					attrValues.get(i).add(tmp);
				}
			}
		}
		setFillViews();
		
	}
	
	
	//---------------------------------------------------------------------------LISTENERS
	
	
	
	
	final OnTabChangeListener otchlistener = new OnTabChangeListener() {
		@Override
		public void onTabChanged(String tabId) {
			Log.w("",tabId);
			if(tabId.equals(FIRST_TAB)){
				
			}
			else if(tabId.equals(CREATE_TABLE_TAB)){
				if(!isTableSizeCorrect()){
					th.setCurrentTabByTag(FIRST_TAB);
					columnNumberTV.setText(viewFlipper.indexOfChild(viewFlipper.getCurrentView()));
					Toast.makeText(MainActivity.this, "Wrong column or row size. Set it first", Toast.LENGTH_SHORT).show();
				}
			}
			else if(tabId.equals(RESULT_TAB)){
				if(!isTableSizeCorrect()){
					th.setCurrentTabByTag(FIRST_TAB);
					Toast.makeText(MainActivity.this, "Wrong column or row size. Set it first", Toast.LENGTH_SHORT).show();
				}
				else{
					
				}
			}
		}
	};
	
	final android.view.View.OnClickListener clickListener = new android.view.View.OnClickListener() {
		@Override
		public void onClick(View v) {
			if(v.getId() == R.id.next){
				int idx =viewFlipper.indexOfChild(viewFlipper.getCurrentView());
				idx = (++idx < viewFlipper.getChildCount())?idx:0;
				viewFlipper.setDisplayedChild(idx);
				columnNumberTV.setText(String.valueOf(idx));
				attrNameET.setText(attrNames[idx]);
			}
			else if(v.getId() == R.id.prev){
				int idx =viewFlipper.indexOfChild(viewFlipper.getCurrentView());
				idx = (--idx < 0)?viewFlipper.getChildCount()-1:idx;
				viewFlipper.setDisplayedChild(idx);
				columnNumberTV.setText(String.valueOf(idx));
				attrNameET.setText(attrNames[idx]);
			}
			else if(v.getId() == R.id.addValBT){
				String attrValue = attrValueET.getText().toString();
				if(!attrValue.equals("")){
					attrValues.get(viewFlipper.indexOfChild(viewFlipper.getCurrentView())).add(attrValue);
					attrValueET.setText("");
				}
			}
		}
	};
	
	final OnLongClickListener longClickListener = new OnLongClickListener() {
		
		@Override
		public boolean onLongClick(View v) {
			
			
			
			if(!attrNameET.isFocusable()){
				setAttribNameEditMode(true);
				
			}
			else{
				setAttribNameEditMode(false);
				
			}
			return true;
		}
	};
	
	final OnItemClickListener oicl =  new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> arg0, View view, int position,long arg3) {
			final TextView clicked = (TextView) view;
			final BaseAdapter adapter = (BaseAdapter) arg0.getAdapter();
			final int row = position;
			
			ArrayList<String> tmpValues = attrValues.get(viewFlipper.indexOfChild(viewFlipper.getCurrentView()));
			
			final String [] s = new String[tmpValues.size()];
			tmpValues.toArray(s);
			
			
			AlertDialog.Builder b = new Builder(MainActivity.this);
			b.setTitle("values");
			
			
			b.setItems(s, new OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Log.i("dialog", s[which]);
					columns.get(viewFlipper.indexOfChild(viewFlipper.getCurrentView())).set(row, s[which]);
					adapter.notifyDataSetChanged();
				}
			});
			b.show();
			
		}
		
	};
	
	final FileFilter tabFileFilter = new FileFilter() {
		@Override
		public boolean accept(File pathname) {
			String name = pathname.getName();
			name = name.substring(name.lastIndexOf("."), name.length());
			return name.equals(".tab");
		}
	}; 
	
	static class SaveState implements Serializable{
		/**
		 * 
		 */
		private static final long serialVersionUID = 511344387442452785L;
		ArrayList<ArrayList<String>> columns;
		ArrayList<ArrayList<String>> attrValues;
		String [] attrNames;
		int rowCount;
		int colCount;
		
		public SaveState(ArrayList<ArrayList<String>> columns, ArrayList<ArrayList<String>> attrValues, String [] attrNames ,int rowCount, int colCount){
			this.attrNames = attrNames;
			this.attrValues = attrValues;
			this.colCount = colCount;
			this.columns = columns;
			this.rowCount = rowCount;
		}
	}

}
